#ifndef GB_ROM_H
#define GB_ROM_H

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

typedef enum GBCartType
{
	GBCartROMOnly = 0x0,
	GBCartMBC1 = 0x1,
	GBCartMBC1RAM = 0x2,
	GBCartMBC1RAMBattery = 0x3,
	GBCartMBC2 = 0x5,
	GBCartMBC2Battery = 0x6,
	GBCartRAM = 0x8,
	GBCartRAMBattery = 0x9,
	GBCartMMM01 = 0xB,
	GBCartMMM01RAM = 0xC,
	GBCartMMM01RAMBattery = 0xD,
	GBCartMBC3TimerBattery = 0xF,
	GBCartMBC3TimerRAMBattery = 0x10,
	GBCartMBC3 = 0x11,
	GBCartMBC3RAM = 0x12,
	GBCartMBC3RAMBattery = 0x13,
	GBCartMBC4 = 0x15,
	GBCartMBC4RAM = 0x16,
	GBCartMBC4RAMBattery = 0x17,
	GBCartMBC5 = 0x19,
	GBCartMBC5RAM = 0x1A,
	GBCartMBC5RAMBattery = 0x1B,
	GBCartMBC5Rumble = 0x1C,
	GBCartMBC5RumbleRAM = 0x1D,
	GBCartMBC5RumbleRAMBattery = 0x1E,
	GBCartMBC6RAMBatteryFlash = 0x20,
	GBCartMBC7 = 0x22,
	GBCartRocket = 0x97,
	GBCartRocketRAM = 0x99,
	GBCartPocketCamera = 0xFC,
	GBCartBandaiTama5 = 0xFD,
	GBCartHuC3 = 0xFE,
	GBCartHuC1RAMBattery = 0xFF,
} GBCartType;

typedef enum GBCartCountry
{
	GBCartJapan
} GBCartCountry;

typedef enum GBCartMBCType
{
    GBCartMBCNone,
    GBCartMBC1,
    GBCartMBC2,
    GBCartMBC3,
    GBCartMBC4,
    GBCartMBC5,
    GBCartMBC5Rumble,
    GBCartMBCMMM,
    GBCartMBCCamera,
    GBCartMBCTAMA5,
    GBCartMBCHUC3,
    GBCartMBCHUC1,
    GBCartMBC8In1,
    GBCartMBCCollection,
    GBCartMBCPokemon2In1,
    GBCartMBCRocket,
    GBCartMBC7,
    GBCartMBC6
} GBCartMBCType;

typedef enum GBCartMBCSelectType
{
    GBCartMBCSelectROM,
    GBCartMBCSelectRAM,
    GBCartMBCSelectRTC
} GBCartMBCSelectType;

typedef struct GBCart
{
    char title[17]; // game title
	char manufacturer[5]; // manufacturer code
	bool isColor; // CGB flag
	bool isSuper; // SGB flag
	uint8_t type; // ROM type
	uint16_t romSize; // ROM size in KByte
	uint16_t ramSize; // RAM size in KByte
	uint8_t country; // destination code
	uint16_t licensee; // licensee code
	uint8_t maskROMVersion; // mask ROM version number

	uint8_t headerChecksum; // header checksum
	bool isHeaderValid; // if checksum is valid
	uint16_t checksum; // global checksum
	bool isValid;

	bool hasValidLogo; // pass Nintendo logo test
	//bool isCommercial; // is it a commercial ROM?

    struct GBCartMBC
    {
        GBCartMCBType type;
        bool hasRAM;
        bool hasBattery;
        bool hasTimer;
        uint16_t maxROMBank;
        uint8_t maxRAMBank;
        uint16_t romBank;
        uint8_t ramBank;
        uint8_t currRAMBank;
        uint8_t timeRegister;
        GBMBCSelectType select;
        bool hasExternalRAM;
        bool hasRealTimeClock;
        int gameSwitched; // already switch game in multi-game cartridge?

        // MBC1 only
        uint16_t highROMBank;
        uint16_t lastAddr;
    } mbc;

    uint8_t * rom; // TODO: load this!
    uint8_t * ram;
} GBCart;

#endif
